package com.xayy.scheduled.jobs;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xayy.core.antlr4.utils.GroovyScriptUtils;
import com.xayy.ds.model.DsAssessTaskInfo;
import com.xayy.ds.model.DsDataInfo;
import com.xayy.ds.model.DsHealthDeep;
import com.xayy.ds.model.DsNodeTreeInfo;
import com.xayy.ds.service.DsAssessTaskInfoService;
import com.xayy.ds.service.DsDataInfoService;
import com.xayy.ds.service.DsHealthDeepService;
import com.xayy.ds.service.DsNodeTreeInfoService;
import com.xayy.mgt.model.HealthDeep;
import com.xayy.mgt.model.NodeTreeInfo;
import com.xayy.mgt.service.HealthDeepService;
import com.xayy.mgt.service.NodeInfoService;
import com.xayy.scheduled.ScheduledTaskContext;
import com.xayy.scheduled.model.AssessTaskInfo;
import com.xayy.scheduled.model.DataInfo;
import com.xayy.scheduled.model.dto.AssessTaskInfoDto;
import com.xayy.scheduled.service.AssessTaskInfoService;
import com.xayy.scheduled.service.DataInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class AssessJob {
    @Autowired
    DsNodeTreeInfoService nodeInfoService;
    @Autowired
    DsHealthDeepService healthDeepService;
    @Autowired
    DsAssessTaskInfoService assessTaskInfoService;
    @Autowired
    DsDataInfoService dataInfoService;

    public void execute(String NodeId){
        Long taskId= ScheduledTaskContext.getCurrentTaskId();
        DsAssessTaskInfo assessTaskInfo=assessTaskInfoService.selectTById(taskId);
        DsNodeTreeInfo nodeTreeInfo = nodeInfoService.getNode(Long.parseLong(NodeId));
        if (null == nodeTreeInfo){
            log.error("查询不到该节点信息");
            return;
        }
        double healthScore=traverseChildNodes(nodeTreeInfo,assessTaskInfo);


        //修改调度任务上的健康值信息

        assessTaskInfo.setHealthScore(healthScore);
        assessTaskInfoService.updateT(assessTaskInfo);
    }
    public void execute(){
        log.info("执行扫描方法逻辑-无参");
    }

    private List<Integer> healthAssess(DsAssessTaskInfo assessTaskInfo, DsHealthDeep healthDeep){
        AssessTaskInfoDto dto = AssessTaskInfoDto.builder()
                .startTime(assessTaskInfo.getStartTime())
                .endTime(assessTaskInfo.getEndTime())
                .build();
        DsDataInfo dataInfo = dataInfoService.getByCode(healthDeep.getParamCode());
        HttpResponse getDataRequest = null;
        try {
            getDataRequest = HttpUtil.createRequest(Method.POST, dataInfo.getHttpAddr()).body(JSON.toJSONString(dto)).execute();
        } catch (Exception e) {
            log.error("调用接口失败：" + e.getMessage());
        }
        if (null != getDataRequest && getDataRequest.getStatus() == 200){
            JSONObject result = JSON.parseObject(getDataRequest.body());
//            log.info("查询数据成功，返回值：");
//            log.info(String.valueOf(result));
            List<Integer> dataList = result.getJSONArray("data").toJavaList(Integer.class);
            /**查询不到数据就停止任务*/
            if (null==dataList || dataList.size()==0){
                log.error("未查询到对应数据");
                return null;
            }else {
                return dataList;
            }
        }else {
            log.error("调用接口失败："+getDataRequest.getStatus());
            return null;
        }
    }

    private double traverseChildNodes(DsNodeTreeInfo nodeTreeInfo, DsAssessTaskInfo assessTaskInfo){
        DsHealthDeep healthDeep = healthDeepService.getByNodeId(nodeTreeInfo.getId());
        List<DsNodeTreeInfo> nodeTreeInfoList = nodeInfoService.getByParentId(nodeTreeInfo.getId());

        if (null == nodeTreeInfoList || nodeTreeInfoList.size() == 0){
            log.info(nodeTreeInfo.getNodeName() + "节点没有子节点");
            double health = getScriptHealth(nodeTreeInfo.getId(), healthAssess(assessTaskInfo, healthDeep));
            log.info(nodeTreeInfo.getNodeName() + "节点健康度" + health);
            updateHealth(nodeTreeInfo.getId(),String.format("%.2f", health));
            return health;
        }else {
            int count = 0;
            List<Double> argList = new ArrayList<>();
            for (DsNodeTreeInfo info : nodeTreeInfoList){
                double childNodeHealth = traverseChildNodes(info,assessTaskInfo);
                argList.add(childNodeHealth);
                count++;
            }
            double health = getScriptHealth(nodeTreeInfo.getId(), argList);
            log.info(nodeTreeInfo.getNodeName() + "节点有" + count + "个子节点");
            log.info(nodeTreeInfo.getNodeName() + "节点健康度" + health);
            updateHealth(nodeTreeInfo.getId(),String.format("%.2f", health));
            return health;
        }
    }

    private void updateHealth(Long nodeId,String health){
        DsHealthDeep healthDeep = healthDeepService.getByNodeId(nodeId);
        if (null != healthDeep){
            healthDeep.setDataInfo(health);
            healthDeep.setTimeInfo(new Date());
            healthDeepService.updateT(healthDeep);
        }
    }

    private Double getScriptHealth(Long nodeId, Object... args){
        Double health=0.0;
        DsHealthDeep healthDeep = healthDeepService.getByNodeId(nodeId);
        if (null != healthDeep){
            if(StringUtils.isNotBlank(healthDeep.getCustomParam())){
                String groovyScript=healthDeep.getCustomParam();
                try {
                    Object result = GroovyScriptUtils.execute(groovyScript, "execute", args);
                    String healthStr=String.valueOf(result);
                    health=Double.parseDouble(healthStr);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
        return health;
    }
}
